﻿using System;
using CzfSDK;
using System.Collections;
using MySql.Data.MySqlClient;

namespace Server
{
	public static class UserManager
	{
		const string SEND_COIN_COUNT = "RefreshCoin";
		const string SEND_GEM_COUNT = "RefreshGem";
		const string SEND_DUST_COUNT = "RefreshDust";

		public static Hashtable Login(string account, string password, CzfNetClient client)
		{
			CzfLog.Info ("{0} Login".CzfFormat(account));

			Hashtable data = UserManager.Get (account);
			if (data == null) {
				// 用户不存在,创建账号
				throw new CzfProtoException (Constants.ERR3, "账号不存在");
			}else if (data.GetVal<string> ("password") != password) {
				throw new CzfProtoException (Constants.ERR2, "密码错误!");
			}

			var user = new User (data, client);
			if (client != null) {
				client.OnClose += (c) => {
					Game.current.Logout (null, c);
				};
			}

			UserManager.UserLogin (user.id);

			// 检测过期邮件,推送未读邮件数量
			MailManager.DayCheck(user.id);

			var ret = user.data;
			// 拼上竞技场胜点信息
			var arena0 = ArenaManager.GetUserArena(user.id, 0);
			var arena1 = ArenaManager.GetUserArena(user.id, 1);

			ret ["arenawin1"] = arena1.GetVal<int>("stars");
			ret ["arenawin2"] = arena0.GetVal<int>("stars");

			return ret;
		}


		static object user_lock = new object ();
		// 注册账号
		public static Hashtable CreateUser(string account, string name, string password, CzfNetClient client)
		{
			lock (user_lock) {
				var h = Get (account);
				if (h != null)
					throw new CzfProtoException (Constants.ERR4, "账号已存在");

				h = GetByName (name);
				if (h != null || CheckName(name))
					throw new CzfProtoException (Constants.ERR5, "昵称已存在");

				CreateUser2 (account, name, password);
			}
			return Login (account, password, client);
		}

		static Hashtable CreateUser2(string account, string name, string password)
		{
			var data = UserManager.Create(account, name, password);
			int userid = data.GetVal<int> ("id");

			// 初始资源
			string prize = MConfig.GetGameConfig<string> ("initPrize");
			BagManager.AddItem (prize, userid, "创建账号初始获得");

			// 初始化角色
			prize = "";
			if (CzfRandom.Range (100) > 50)
				prize = "100003,1";
			else
				prize = "100002,1";
			BagManager.AddItem (prize, userid, "创建账号初始获得");

			// 初始化阵容
			var formations = FormationManager.GetAll (userid);
			FormationManager.ChangeNowFormation (formations [0].GetVal<int> ("id"), userid);

			return data;
		}

		public static string SetGuide(int userId, int guide)
		{
			UpdateGuide (userId, guide);
			return "ok";
		}

		#region 玩家金币变动
		public static int TryAddCoin(int userId, int count)
		{
			var user = Get (userId);
			var has = user.GetVal<int> ("coin");
			if (count < 0) {				
				if (has < -count)
					throw new CzfProtoException (Constants.ERR3, "金币不足");
			}
			return has;
		}

		// 给玩家增减金币,返回值为更新后的金币数
		public static int AddCoin(int userId, int count)
		{
			var has = TryAddCoin(userId, count);
			UpdateAddCoin (userId, count);

			var user = User.Get (userId);
			if (user != null && user.client != null) {				
				CzfNetManager.current.Call (user.client, SEND_COIN_COUNT, null, 0, has + count);
			}

			return has + count;
		}
		#endregion

		#region 玩家钻石变动
		public static int TryAddGem(int userId, int count)
		{
			var user = Get (userId);
			var has = user.GetVal<int> ("gem");
			if (count < 0) {				
				if (has < -count)
					throw new CzfProtoException (Constants.ERR3, "钻石不足");
			}
			return has;
		}

		// 给玩家增减钻石,返回值为更新后的数
		public static int AddGem(int userId, int count)
		{
			var has = TryAddGem(userId, count);
			UpdateAddGem (userId, count);

			var user = User.Get (userId);
			if (user != null && user.client != null) {				
				CzfNetManager.current.Call (user.client, SEND_GEM_COUNT, null, 0, has + count);
			}
			return has + count;
		}
		#endregion

		#region 玩家碎片变动
		public static int TryAddDust(int userId, int count)
		{
			var user = Get (userId);
			var has = user.GetVal<int> ("dust");
			if (count < 0) {				
				if (has < -count)
					throw new CzfProtoException (Constants.ERR3, "钻石不足");
			}
			return has;
		}

		// 给玩家增减碎片,返回值为更新后的数
		public static int AddDust(int userId, int count)
		{
			var has = TryAddDust(userId, count);
			UpdateAddDust (userId, count);

			var user = User.Get (userId);
			if (user != null && user.client != null) {				
				CzfNetManager.current.Call (user.client, SEND_DUST_COUNT, null, 0, has + count);
			}

			return has + count;
		}
		#endregion

		#region DB
		// 所有玩家登出
		public static void AllUserLogout()
		{
			var sql = "update loginlog set end=@end, status=2 where status = 1";
			MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@end", DateTime.Now)
			);
		}

		// 玩家登陆
		public static void UserLogin(int userId)
		{
			var sql = "insert into loginlog(userid, start, end, status) values(@userid, @start, @end, 1)";
			MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@userid", userId),
				new MySqlParameter("@start", DateTime.Now),
				new MySqlParameter("@end", DateTime.Now)
			);
		}

		// 玩家登出
		public static void UserLogout(int userId)
		{
			var sql = "update loginlog set end=@end, status=2 where userid=@userid and status = 1";
			MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@userid", userId),
				new MySqlParameter("@end", DateTime.Now)
			);
		}

		// 更新玩家的新手步骤
		public static int UpdateGuide(int userId, int guide)
		{
			var sql = "update user set guide = @guide where id = @id";
			return MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@guide", guide),
				new MySqlParameter("@id", userId)
			);
		}

		// 更新玩家的碎片数
		public static int UpdateAddDust(int userId, int count)
		{
			var sql = "update user set dust = dust + @count where id = @id";
			return MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@count", count),
				new MySqlParameter("@id", userId)
			);
		}

		// 更新玩家的钻石数
		public static int UpdateAddGem(int userId, int count)
		{
			var sql = "update user set gem = gem + @count where id = @id";
			return MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@count", count),
				new MySqlParameter("@id", userId)
			);
		}

		// 更新玩家的金币数
		public static int UpdateAddCoin(int userId, int count)
		{
			var sql = "update user set coin = coin + @count where id = @id";
			return MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@count", count),
				new MySqlParameter("@id", userId)
			);
		}

		// 更新玩家的当前使用阵容
		public static int UpdateNowFormation(int userId, int formationId)
		{
			var sql = "update user set nowformation = @nowformation where id = @id";
			return MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@nowformation", formationId),
				new MySqlParameter("@id", userId)
			);
		}

		public static Hashtable Get(int id)
		{
			if (id < 0)
				id = 1; // NPC

			var sql = "select * from user where id = @id";
			var dr = MysqlPool.current.ExecDataRow (sql,
				new MySqlParameter("@id", id)
			);
			if (dr == null)
				return null;
			else
				return dr.ToHashtable ();
		}

		public static Hashtable Get(string account)
		{
			var sql = "select * from user where account = @account";
			var dr = MysqlPool.current.ExecDataRow (sql,
				new MySqlParameter("@account", account)
			);
			if (dr == null)
				return null;
			else
				return dr.ToHashtable ();
		}

		public static Hashtable GetByName(string name)
		{
			var sql = "select * from user where name = @name";
			var dr = MysqlPool.current.ExecDataRow (sql,
				new MySqlParameter("@name", name)
			);
			if (dr == null)
				return null;
			else
				return dr.ToHashtable ();
		}

		public static Hashtable Create(string account, string name, string password)
		{
			var sql = "insert into user(account, name, password, createtime) values(@account, @name, @password, now())";
			MysqlPool.current.ExecuteNonQuery (sql,
				new MySqlParameter("@account", account),
				new MySqlParameter("@name", name),
				new MySqlParameter("@password", password)
			);
			return Get (account);
		}

		// 从库中随机一个名字
		public static string GetRandomName()
		{
			var sql = "select name from npcname order by rand() limit 1";
			return MysqlPool.current.ExecString (sql);
		}

		// 检测名字是否在随机名字库中
		public static bool CheckName(string name)
		{
			var sql = "select * from npcname where name = @name";
			var dr = MysqlPool.current.ExecDataRow (sql,
				new MySqlParameter("@name", name)
			);
			if (dr == null)
				return false;
			else
				return true; // 已有
		}
		#endregion
	}
}

